package com.ylz.sjzx.sio.sdk.model;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.ylz.sjzx.sio.common.core.annotation.MessageField;
import com.ylz.sjzx.sio.common.core.constant.Const;
import com.ylz.sjzx.sio.common.core.enums.Cmd;
import com.ylz.sjzx.sio.common.core.utils.DeclareFieldUtil;
import com.ylz.sjzx.sio.common.core.utils.GsonUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wiqi
 * @version 1.0
 * @date 2020/12/10
 */
@Slf4j
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class BaseSocketModel implements Serializable {
    private static final long serialVersionUID = 5683014613551448653L;
    /**
     * 命令
     */
    Cmd action;
    /**
     * 参数
     */
    Object param;

    /**
     * true 直接返回param对象 flase 默认不需要toMessage()
     */
    boolean needtoParam;

    public static BaseSocketModel toObj(String data) {
        List list = GsonUtil.json2Bean(data, List.class);
        String action = list.get(0).toString().replace("-", "");
        BaseSocketModel build = BaseSocketModel.builder().action(Cmd.valueOf(action)).build();
        if (list.size() == 2) {
            //判断有参数
            build.setParam(list.get(1));
        } else {
            build.setParam(list);
        }
        return build;
    }

    /**
     * 尽量用List 来注入到param
     * 少用对象反射
     *
     * @return
     * @throws IllegalAccessException
     */
    @SneakyThrows
    public String toMessage() {
        if (this.param != null) {
            if (this.param instanceof Collection && CollectionUtil.isEmpty((Collection) this.param)) {
                return null;
            }
            if (this.param instanceof Map && CollectionUtil.isEmpty((Map) this.param)) {
                return null;

            }
            return this.model2Message();
        }
        return null;

    }

    /**
     * 转为Cmd msg 数组
     *
     * @return
     * @throws IllegalAccessException
     */
    @SneakyThrows
    public String toCmdMessage() {
        List list = new ArrayList();
        list.add(this.action.getValue());
        list.add(this.toMessage());

        return "42" + GsonUtil.bean2Json(list);
    }

    /**
     * 尽量不使用对象反射
     *
     * @return
     * @throws IllegalAccessException
     */
    private String model2Message() throws IllegalAccessException {
        if (this.param == null) {
            return "";
        }
        //标准参数处理方式
        if (DeclareFieldUtil.isStandardProperty(this.param.getClass())) {
            return this.param.toString();
        }
        //集合的话可以直接拼接
        if (this.param instanceof Collection) {
            Collection paramList = (Collection) this.param;
            return paramList.stream().map(obj -> obj.toString()).collect(Collectors.joining(Const.MESSAGE_FLAG))
                    .toString();
        }

        //Map的话可以直接处理返回
        if (this.param instanceof Map) {
            return GsonUtil.bean2Json(this.param);
        }

        return this.toMessageByModel();
    }

    /**
     * 对象的处理方式
     *
     * @return
     * @throws IllegalAccessException
     */
    private String toMessageByModel() throws IllegalAccessException {
        //尽量不使用对象反射
        List valueList = new ArrayList();
        Class<?> aClass = this.param.getClass();
        List<Field> orderedField = DeclareFieldUtil.getOrderedField(aClass);
        for (Field field : orderedField) {
            //设置对象的访问权限，保证对private的属性的访问
            field.setAccessible(true);
            Object value = field.get(this.param);
            if (value == null) {
                continue;
            }
            MessageField annotation = field.getAnnotation(MessageField.class);
            if (StrUtil.isNotBlank(annotation.dateFormat())) {
                //是date
                valueList.add(DateUtil.format((Date) value, annotation.dateFormat()));
            } else if (DeclareFieldUtil.isStandardProperty(value.getClass())) {
                //是常数
                valueList.add(value);
            } else {
                //是对象
                valueList.add(GsonUtil.bean2Json(value));
            }

        }
        return valueList.stream().map(obj -> obj.toString()).collect(Collectors.joining(Const.MESSAGE_FLAG)).toString();
    }

}
